home *** CD-ROM | disk | FTP | other *** search
/ Freaks Macintosh Archive / Freaks Macintosh Archive.bin / Freaks Macintosh Archives / Macintosh / Development & Resource Tools / ROM Sucker.sit / ROM Sucker / PowerPC Assembly Tech Details < prev    next >
Text File  |  1998-01-04  |  15KB  |  69 lines

  1. Warning!  Hacker geeky stuff contained herein!  This file contains info on how ROM Sucker became a PowerPC assembly language fat application.  It explains some of my programming methodology, philosophy, etc.
  2.  
  3. I wrote this because the sample code that I have seen doesn’t look anything like mine.  I thought maybe some other people might be able to relate to my style better and it might give those other guys something to think about.  Nobody knows everything and maybe somebody might learn something from my humble efforts.
  4.  
  5. Background stuff
  6. I programmed this originally in 680x0 assembly language.  I had a bad experience with the Microsoft BASIC compiler on my first Macintosh application back in 1987 and have been programming exclusively in assembly language since then.  I do not like high level languages.  I do program professionally in C at work, but I have had too many wacko things happen that have driven me crazy over the years.
  7.  
  8. My preferred source file is a single text file with the assembly language source and a single include file with all the equates and imports.  I don’t like multiple source files because I can never seem to figure out which file has the DoWidget routine in it.  I don’t like multiple includes for the same reason.  I have found that I only use a small subset of the Mac toolbox and OS calls so one small include file that I take from app to app does it for me.  I’m a simple straightforward kind of guy and all this complicated stuff makes my brain go numb, so I try to keep things as simple as possible.
  9.  
  10. Yes, I did originally write this application on one day.  I was able to do this because I have a hunk of source code called “Application Shell” that already has most of the code I need to build a complete application.  It does all the initialization, handles events, menus, scroll bars, dialog boxes, file input/output, etc.  So I just copy it and make a few modifications as necessary to build a new application.
  11.  
  12. The source file reflects my programming style.  It basically looks exactly like the 680x0 version.  One thing I do is comment a lot.  That’s so I can figure out what I was doing when I come back later.  There have been times when I came back to code I had written and said, “*I* wrote this???  I don’t have any idea what I was trying to do here”.  Also I comment a lot if I fixed a bug or spent a lot of time working with a system weirdness so that I won’t have to go through it again.  Another thing I do is I always put in the Inside Macintosh page number for every Mac system call.  I also frequently put in page numbers of records, definitions, etc.  This makes it much easier later because I tend to adapt old code to new projects and have page numbers to refer to.
  13.  
  14. I tend to keep things tight vertically because I started out with a Mac 512Ke with a 9" screen and still use my SE/30 once in a while.  I’ve spent too many years using a 13" monitor at work, so I’m glad my present employer is enlighted and gave me a 21".
  15.  
  16. Whitespace.  I put blank lines between Mac routine calls.  This groups the setup stuff with each call so I can see what’s going on.  I also put blank lines where it logically makes sense so that if I need to modify something the relevant code is grouped in one place.
  17.  
  18. Stack frames.  I don’t like stack frames.  I can never figure out the offsets to get to the passed values.  Since I’m not passing any values on the stack and use registers for local variables there are no stack frames in this code.
  19.  
  20. I hate underscores.  My fumbly little fingers always get confused and I end up with dashes instead, so I try to avoid using them.  So all my labels follow the old Mac mix of upper and lower case.
  21.  
  22. Since this is my very first PowerPC assembly language app, you’ll have to excuse my ignorance on how to do things correctly and efficiently.  I believe straightforward coding is much more productive in the long run than esoteric complicated constructs.  I didn’t even align my halfwords in the .def file.  If this offends you, please explain to me how much difference it will make in the speed of my code (use nanoseconds because they look so much bigger and more impressive than microseconds).
  23.  
  24. On to the code...
  25. First there is a little header to explain what this source is.  Then the bug list.  Yes, there is a bug, but I didn’t think it was worth the effort to fix it, since this is just a little hack which won’t impact too many lives.
  26.  
  27. We initialize and go into SetupStuff, which is an application-specific section that I use to set things up for this particular application.  For example, there is some cursor stuff in here because I use an animated cursor later.  WindowSetup, TextSetup and MakeMenu are standard stuff.  AlmostReady is more application-specific.  Most of the routines called from here are standard.  Only GetTheResources and SaveTheResources are specific to this app.
  28.  
  29. EventLoop.  I use CaretTime for the WaitNextEvent sleep interval because I read somewhere that it is a Good Thing.  I do not check for a zero result because I usually use NullEvent to call TEIdle to blink the cursor during idle times.  Since I’m not doing any text cursor stuff here there is no NullEvent routine.  I don’t handle Quit the way most people do.  Most people set a Quit flag in some other routine and then check it during the EventLoop routine.  Why?  Just branch directly to the Quit routine and be done with it.  I felt I should use toc_routines here, but there were too many holes in the event numbers, so...
  30.  
  31. MouseDown.  I did use toc_routines here, just for the experience.  I wrote my own dispatcher.  I don’t know if it’s good or bad.  Also you might notice a comment here, “shouldn’t get here”.  I usually try to plug up all the holes so my code won’t leak out.  I once debugged someone else’s remote telemetry code that expected commands between 1 and 20.  He didn’t put in a DEFAULT escape at the end of his CASE list.  The customer was sending a 99 code as a test during the setup of the system and his code fell through to the following routine and went off into la-la land and crashed.  When I talked to him about it, he said, “Well, 99 is an illegal code”.  I said, “What happens if there is noise on the line and the command number gets garbled?”  He said, “That shouldn’t happen”.  Maybe it will.  Maybe it won’t.  So I put up a brick wall.  Don’t get burned on this.
  32.  
  33. You may notice that I don’t have very many mflr/mtlr/blr combos in my routines.  In most cases I’m branching directly back to EventLoop, so there is no need to preserve the LR register.  Saves time, takes less code space, less space on my tiny screen and isn’t needed anyway.
  34.  
  35. Menu stuff.  Most of this is pretty straightforward.  The Apple menu routine handles old-style Desk Accessories (the kind you installed in applications with Font/DA Mover).  I don’t think anyone still uses these, but the code is left over from years ago.
  36.  
  37. Do About.  A lot of people use PICTs in their About box.  I never have.  Maybe one day I’ll take the time to figure out how to do it.  So I just use TETextBox, which works for me.  On the 680x0 side, I had to write my own because TextBox didn’t work the way I wanted, but TETextBox works just fine here.  I don’t use ModalDialog because I like to be able to click the mouse or hit a key to dismiss the About box.  With ModalDialog you need a customized filterProc to do this.   Also, the mouse click must be inside the dialog box.  With a 21" screen at work and a 20" at home, I hate mousing all over the screen to get to the dialog box.  Actually it’s not hard at all to place the cursor anywhere you want on the screen, the one thing that Windows programmers do (though very poorly in most cases, in my opinion.  They never put the cursor back where it was before the dialog box appeared.  *I* put it back in my FKEYZoom FKEY, so why can’t they?  There’s more, but I digress…) that Mac programmers don’t.  The disadvantage to using WaitNextEvent here is that you can’t respond to update events for the dialog box.  This means that you have to do all the drawing inside the box right here.  Plus your DITLs will need to be drawn explicitly.  One aspect of this is that I don’t use any DITLs, but I need at least one anyway or the dialog box will be invisible.  Gotcha!
  38.  
  39. EditMenu.  These commands are left over from the old Desk Accessory days when a DA would use your app’s menus.  If you didn’t handle the editing commands then the command key equivalents wouldn’t work in the DA.
  40.  
  41. Options menu.  The only option is smooth vs. normal scrolling.  I have been fascinated with smooth scrolling ever since Don Lancaster implemented it on the Apple II.  It’s great because you can actually read the text as it scrolls.  It’s not so great because it is extremely slow.  I felt that a PowerPC would be fast enough to make it practical.  My C implementation was disappointing.  So assembly is going to fix all this, right?  Wrong.  It turns out that TEScroll (still 680x0 emulated code) is the bottleneck.  I want to rewrite TEScroll in PPC assembly.  It remains to be seen if that will fix it.  Try it out.  It’s not too bad with a small window, but becomes glacial when the window is large.  Lots of pixels to move.
  42.  
  43. Scrolling routines.  I tried to keep the inner loop as small as possible to speed things up.  The PageUp and PageDown routines need a little delay because they go too fast.  I got burned badly by Delay because I was used to the 680x0 version.  I didn’t realize that I needed to set up r4.  It contained $0E80, left over from the TEScroll.  This is right in the middle of the trap dispatch table.  ROM Sucker worked fine, but other applications would crash when they tried to call Get1NamedResource, which vectors through $0E80.  Oops.  I’m glad I’m pretty good with MacsBug.  It only took most of the day (on my bonus day off that my boss gave me for finishing my last project early) to find that one.
  44.  
  45. DoDrag, etc.  The standards.  Use the toolbox routines and you’re done.  Here’s where my remaining bug comes into play.  If the text has been scrolled and the window is made larger, the CalControl routine is not able to handle this case.  The scroll bar calibration gets all messed up and you end up with a lot of white space and can’t scroll all of the text back into view.  I figured this wasn’t worth the effort to fix here.  I’ve got too many other programming projects in the works and the situation isn’t likely to occur anyway.
  46.  
  47. KeyDown and ControlChar.  This is the way I do it.  It works for me.  I have in the past handled the Help key by putting up my About box, if that was appropriate.  One time I asked for help from anyone who pressed this key.  Never did fix that one (or get any responses, either).  It’s kind of an Easter Egg for anybody who uses my Diccionario Spanish/English dictionary.
  48.  
  49. UpdateEvent and Activate/Deactivate.  I have never been able to get this to work the way I wanted.  I always get a flicker on the first update event no matter what I do.  Maybe I’ll figure this one out someday.  The Activate/Deactivate/OSEvent is standard stuff.
  50.  
  51. HighLevelEvent.  I’m really cheating here.  I do know how to handle these events and have done so in other apps, but the legal way is so cumbersome and I don’t need anything but Quit, which is easy to handle.
  52.  
  53. GetTheResources.  The first half of the real meat of this whole thing.  I did this a lot differently in the 680x0 version, but live and learn as they say.  This one is much more straightforward and doesn’t use any system calls (see SaveTheResources).  Basically it walks through the ROM’s resource map and pulls out all the resource info.  This is pretty esoteric stuff, so I won’t bother explaining it.  If you really want to know how a resource map works, check out Inside Macintosh.
  54.  
  55. NumberToString.  I used the NumToString routine in the 680x0 version.  This was one of the first things I did when I converted this app to PPC assembly, and I couldn’t get NumToString to work no matter what I did.  So I wrote my own.  It wasn’t until I was comparing the output to the ResEdit file that I noticed that the ResEdit version showed some of the ID numbers as negative.  Another oops.  So I rewrote it to handle negative numbers.  The 680x0 version still has all positive numbers.
  56.  
  57. CenterWindow, etc.  Standard stuff.  I size my destination and view rectangles so that they are just big enough for complete lines to fit.  I hate partial lines at the bottom of windows.  Sorry.  CalControl sets things up so that the control value is the number of the topmost line visible in the window.  I just figured this out on my own and I guess other people do it the same way, if some sample code I recently saw is any indication.
  58.  
  59. SaveTheResources.   This does essentially the same thing as GetTheResources, but puts them into a file instead of into a text record.  This time we have to use the system routines that I took out of GetTheResources.  I futz with the cursor here to let the user know something is happening.  I also programmed a progress bar dialog and made it an option until I realized that you wouldn’t be able to select the option until after the routine had already executed!  Oops, again.  The animated cursor was cuter anyway, so you get to watch Clarus doing backflips.  Since InitCursorCtl and SpinCursor don’t seem to really be toolbox routines (there are no A-traps associated with them that I could find), despite what Inside Macintosh says, I did my own.  I don’t know if this is the “right” way, it’s just the way I did it.
  60.  
  61. NewResourceFile.  I used HDelete to delete the old file in the 680x0 version, but it didn’t work here, so I futzed around until I found PBHDeleteSync and got it to work.  I didn’t try the Async versions of these routines.  I’m not really clear on when they work anyway.  I just read that a lot of time the system will act as if the Sync version had been called anyway, depending on the conditions.  It makes sense to me that you would want PBHGetFInfo to complete before trying to do a PBHSetFInfo, so that’s why they’re Sync.  Better safe than sorry.
  62.  
  63. Quit.  Does what it says.  I noticed in the sample source code that I’ve looked at that tidy_up is always followed by blr.  I looked at the tidy_up macro and saw it already had one, so I left it off.  I’ve always used ExitToShell to end my 680x0 apps.  I don’t know if it could be used here.  Actually, I MacsBugged past the end of my code and ExitToShell got executed somewhere in there anyway, I guess by the Finder.
  64.  
  65. Data section.  I didn’t put “data” after the AboutTextEnd label and Anvil couldn’t find it.  Don’t ask me, I just do what I have to do to make it work.
  66.  
  67. Equate section.  I tried to put these in a MyEquates.s file, but Anvil acted like it wasn’t there.  I don’t know if it’s not possible or I just did it wrong, so they’re back here.  I would really love to have a universal MyEquates file that I could reuse with all my apps, but couldn’t figure out a way to do it with Anvil.  (That’s a hint to all you more knowledgeable types who could help me out here).
  68.  
  69. DebugString.  I just leave this stuff here at the end.  If I need a DebugStr it’s easy to modify it here and paste it into the appropriate place.  It still has the StepSpy on $0E80 that I used to find my Delay bug.